package com.hunttown.common.dao.datasource;

import java.sql.Connection;
import java.sql.SQLException;
import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;
import javax.sql.DataSource;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.jdbc.datasource.AbstractDataSource;

public class MasterSlaveDataSource extends AbstractDataSource {
    private static final Logger logger = LoggerFactory.getLogger(MasterSlaveDataSource.class);
    private String masterDataSourceBeanName;
    private DataSource masterDataSource;
    private int slaveCount;
    private List<String> slaveDataSourceBeanNames;
    private List<DataSource> slaveDataSources;
    private AtomicInteger counter = new AtomicInteger(0);

    public MasterSlaveDataSource() {
    }

    public void setMasterDataSource(DataSource masterDataSource) {
        this.masterDataSource = masterDataSource;
    }

    public void setMasterDataSourceBeanName(String masterDataSourceBeanName) {
        this.masterDataSourceBeanName = masterDataSourceBeanName;
    }

    public DataSource getMasterDataSource() {
        return this.masterDataSource;
    }

    public void setSlaveDataSources(List<DataSource> slaveDataSources) {
        this.slaveDataSources = slaveDataSources;
        if (slaveDataSources != null) {
            this.slaveCount = slaveDataSources.size();
        }

    }

    public void setSlaveDataSourceBeanNames(List<String> slaveDataSourceBeanNames) {
        this.slaveDataSourceBeanNames = slaveDataSourceBeanNames;
    }

    public Connection getConnection() throws SQLException {
        return this.selectDataSource().getConnection();
    }

    public Connection getConnection(String username, String password) throws SQLException {
        return this.selectDataSource().getConnection(username, password);
    }

    public DataSource selectDataSource() {
        if (this.slaveCount != 0 && !MasterSlaveSwitcher.isForceReadMaster()) {
            if (MasterSlaveSwitcher.isReadSlave()) {
                int index = (this.counter.incrementAndGet() - 1) % this.slaveCount;
                if (index < 0) {
                    index = -index;
                }

                logger.debug("select slave datasource [{}]", this.slaveDataSourceBeanNames.get(index));
                return (DataSource) this.slaveDataSources.get(index);
            } else {
                logger.debug("select master datasource [{}]", this.masterDataSourceBeanName);
                return this.masterDataSource;
            }
        } else {
            logger.debug("no slave or force read master, select master datasource [{}]", this.masterDataSourceBeanName);
            return this.masterDataSource;
        }
    }

    public String toString() {
        return "MasterSlaveDataSource{masterDataSourceBeanName='" + this.masterDataSourceBeanName + '\'' + ", slaveCount=" + this.slaveCount + ", slaveDataSourceBeanNames=" + this.slaveDataSourceBeanNames + ", counter=" + this.counter + '}';
    }
}